package com.qjs.smterp.web.beans;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import org.apache.commons.io.IOUtils;
import com.qjs.smterp.utils.TextUtil;
import com.qjs.smterp.web.utils.FacesContextUtils;

public abstract class AbstractManagedBeanSimple<I, F> extends
	AbstractManagedBean<I, F> {

    protected abstract List<I> searchListCallback(F filter) throws Exception;

    protected abstract String deleteCallback(I item) throws Exception;

    @Override
    protected I[] searchCallback(F filter) throws Exception {
	throw new Exception("Method not implemented");
    }

    @SuppressWarnings("unchecked")
    protected I cloneItem(I item) {
	ObjectOutputStream os = null;
	ObjectInputStream is = null;

	try {
	    ByteArrayOutputStream bos = new ByteArrayOutputStream();
	    os = new ObjectOutputStream(bos);
	    os.writeObject(item);
	    os.flush();
	    ByteArrayInputStream bis = new ByteArrayInputStream(
		    bos.toByteArray());
	    is = new ObjectInputStream(bis);
	    I clone = (I) is.readObject();
	    return clone;
	} catch (Exception e) {
	    FacesContextUtils.addErrorExceptionMessage(e);
	    logger.error("", e);
	    throw new RuntimeException("An error occures at cloneItem method",
		    e);
	} finally {
	    IOUtils.closeQuietly(is);
	    IOUtils.closeQuietly(os);
	}
    }

    public AbstractManagedBeanSimple() {
	super();
    }

    @Override
    public String search() {
	try {
	    list = searchListCallback(filter);
	    setSelectedId(null);
	    setCurrentPage(1);

	} catch (Exception e) {
	    FacesContextUtils.addErrorExceptionMessage(e);
	    logger.error("", e);
	}
	editMode = false;
	return null;
    }

    @Override
    public String modify() {
	setItem(cloneItem(selected));
	editMode = Boolean.TRUE;

	return null;
    }

    @Override
    public String doDelete() {
	String result;

	try {
	    result = deleteCallback(getSelected());
	    search();
	} catch (Exception e) {
	    FacesContextUtils.addErrorExceptionMessage(e);
	    logger.error("", e);
	    result = null;
	}
	return result;
    }

    @Override
    public void setSelectedId(String selectedId) {
	if (TextUtil.isEmpty(selectedId)) {
	    selectedIdx = null;
	} else {
	    selectedIdx = Integer.valueOf(selectedId);
	}
	takeSelection();
    }

    @Override
    public String getSelectedId() {
	return TextUtil.toStringOrNull(selectedIdx);
    }

    public void takeSelection() {
	if (TextUtil.isInBound(list, selectedIdx)) {
	    selected = list.get(selectedIdx);
	} else {
	    selected = newItem();
	}
    }

    @Override
    public I getItem(String id) {
	if (TextUtil.isNotEmpty(id)) {
	    int idx = Integer.parseInt(id);
	    if (TextUtil.isInBound(list, idx)) {
		return list.get(idx);
	    }
	}
	return null;
    }

    public int getCurrentPage() {
	return currentPage;
    }

    public void setCurrentPage(int currentPage) {
	this.currentPage = currentPage;
    }

    private int currentPage = 1;
    private Integer selectedIdx;

}